export {};
require('json5/lib/register');
const gulp = require('gulp');
const JSON5 = require('json5');
const fs = require('fs');
const del = require('rimraf');
const _ = require('lodash');
const log = require('fancy-log');
const Path = require('path');
const glob = require('glob')
const mkdirp = require('mkdirp');
const newer = require('gulp-newer')
const through = require('through2')
const url = require('url')


let {toPath,getFullPath, runCmdDetached, runCmd, buildTarget, delBuildDirAndFile, templateFileGen} = require('sulp_utils')

import {InitInterface} from "../protocol/initInterface"

let flow:InitInterface

let workName

let urlParam:string =''

let asName

let addFlows=[]

gulp.task('init:project', () => {
  return new Promise((resolve)=>{

    if(fs.existsSync(flow.projectPath)){
      console.log("\n NOTE: The project has exist! \n")
      process.exit()
    } else {
      mkdirp.sync(flow.projectPath)
      mkdirp.sync(flow.projectPath+'/.sulp_root')
    }

    const simPath = toPath(flow.projectPath, 'sim')
    mkdirp.sync(simPath)

    const rtlPath  = toPath(flow.projectPath, 'rtl')
    mkdirp.sync(rtlPath)

    const docsPath  = toPath(flow.projectPath, 'docs')
    mkdirp.sync(docsPath)

    const fpgaPath  = toPath(flow.projectPath, 'fpga')
    mkdirp.sync(fpgaPath)

    const asicPath  = toPath(flow.projectPath, 'asic')
    mkdirp.sync(asicPath)

    const signoffPath  = toPath(flow.projectPath, 'signoff')
    mkdirp.sync(signoffPath)

    const configPath  = toPath(rtlPath, '_config')
    const configJsonPath  = toPath(configPath, 'json')
    mkdirp.sync(configJsonPath)

    fs.copyFileSync('template/work.ts', toPath(flow.projectPath,'work.ts'))
    fs.copyFileSync('template/README.md', toPath(flow.projectPath,'README.md'))

    gitInitProject(flow.projectPath)

    resolve()
  })
})

function genStartFiles(templateMap:any){
  const workTemplateVars = {
    workName   : workName,
    projRootPath : flow.projectPath,
  }

  for (let t of templateMap) {
    templateFileGen(t.src, t.target, workTemplateVars)
  }
}

function gitInitProject(projectPath: string){
  return runCmd('git', ['init'], projectPath)
    .then(() => {
      return runCmd('git', ['add', '.'], projectPath)
    })
    .then(() => {
      return runCmd('git', ['commit', '-m', 'initial project'], projectPath)
    })
}

gulp.task('new:component',()=>{
  return new Promise((resolve)=>{
    const configCSV = toPath(flow.workDir,'_config/proj_module_config.csv')
    const list=[]
    if(urlParam.match(/^https:/)||urlParam.match(/^ssh:/)||urlParam.match(/^http:/)) {
      const urlInfo = url.parse(urlParam)
      const componentName = Path.basename(urlInfo.path,'.git')
      list.push(urlParam)
      if(asName===null) {
        list.push(componentName)
      } else {
        list.push(asName)
      }
    } else {
      const componentName = Path.basename(urlParam)
      list.push(getFullPath(flow.workDir,urlParam))
      if(asName===null) {
        list.push(componentName)
      } else {
        list.push(asName)
      }
    }
    list.push('True')
    list.push('master')
    list.push('default')
    if(!fs.existsSync(configCSV)) {
      fs.writeFileSync(configCSV,'url,path,submodule,branch,config\n','utf8')
    }
    fs.appendFileSync(configCSV,list.join(',')+'\n','utf8')
    resolve()
  })
})

gulp.task('new:case',()=>{
  const templateFiles = glob.sync(`${toPath("template/sim_case/**")}`)
  const casePath= toPath(flow.workDir,workName)
  mkdirp.sync(casePath)
  return gulp.src(templateFiles,{base: toPath('template/sim_case')})
    .pipe(gulp.dest(casePath))
})

gulp.task('new:sim',()=>{
  return new Promise((resolve)=>{
    const simPath = toPath(flow.workDir,workName)
    mkdirp.sync(simPath)

    copySimTemplate(simPath)

    resolve()
  })
})

function copySimTemplate(workDir: string){
  const templateFiles = glob.sync(`${toPath("template/sim/**")}`)
  gulp.src(templateFiles,{base: toPath('template/sim')})
    .pipe(gulp.dest(workDir))
    .on('end',()=>{
      const files = glob.sync(`${toPath(workDir,"**/*.template")}`)
      const templateMap = []
      for(const i of files) {
        const fileInfo = Path.parse(i)
        templateMap.push(
          {
            src: i,
            target: toPath(fileInfo.dir, fileInfo.name)
          },
        )
      }
      let addFlowStr=''
      for(const i of addFlows) {
        addFlowStr +=`{flow:require('flow/${i}.ts')},\n`
      }

      for (let t of templateMap) {
        templateFileGen(t.src, t.target, {
          simPath: workDir,
          addFlow: addFlowStr,
        })
      }
      for(const i of templateMap) {
        del.sync(i.src)
      }
    })
}

gulp.task('new:fpga',()=>{
  return new Promise((resolve)=>{
    const verifWorkPath   = flow.workDir
    mkdirp.sync(verifWorkPath)

    const templateMap = [
      {
        src: toPath('template/fpga/work.ts.template'),
        target: toPath(verifWorkPath, 'work.ts')
      },
    ]
    genStartFiles(templateMap)

    resolve()
  })
})

gulp.task('new:file',()=>{
  return new Promise((resolve)=>{
    resolve()
  })
})

gulp.task('new:mem',()=>{
  return new Promise((resolve)=>{
    resolve()
  })
})

gulp.task('new:signoff',()=>{
  return new Promise((resolve)=>{
    resolve()
  })
})


module.exports.init = function(program) {
  program.allowUnknownOption()
    .option('-p, --path <args>', 'specify project root path')
    .option('-n, --name <args>', 'specify sim name')
    .option('-u, --url <args>', 'specify component url/directory')
    .option('--addFlow <flow_names>', 'specify add flow names,separated by comma')
    .option('--as <arg>', 'specify component mount target name')
};

module.exports.flowName='init_project'

const searchRoot=(path)=>{
  if(fs.existsSync(path+'/.sulp_root')) {
    return path
  } else {
    if(path==='/') {
      return null
    } else {
      const pPath=Path.dirname(Path.resolve(path))
      return searchRoot(pPath)
    }
  }
}

module.exports.setEnv = function(e) {
  let env = e

  flow = <InitInterface>env.getFlow('init_project');

  flow.workDir = env.flow.global.workDir

  const projectPath = env.getOpt('init_project.path',searchRoot(flow.workDir))

  if(projectPath) {
    flow.projectPath = getFullPath(flow.workDir,projectPath)
  }

  workName = env.getOpt('init_project.name','demo')

  urlParam=env.getOpt('init_project.url',null)

  asName = env.getOpt('init_project.as',null)

  const addFlowStr=env.getOpt('init_project.addFlow',null)
  if(addFlowStr) {
    addFlows = addFlowStr.trim().split(/,/)
  }
};
